﻿using System;
using Validity.Localization;

namespace Validity.Rules
{
  public interface IRule<TObject, TValue>
  {
    Boolean IsViolatedBy(TObject obj, TValue value);
    RuleViolation GetRuleViolation(TObject obj, TValue value);
  }

  public class Rule<TObject, TValue>
    : IRule<TObject, TValue>
  {
    private readonly Func<TObject, TValue, Boolean> _constraint;
    private readonly Func<TObject, TValue, String> _messageFactory;

    public Rule(Func<TObject, TValue, Boolean> constraint, Func<TObject, TValue, String> messageFactory)
    {
      Verify.NotNull(constraint);
      Verify.NotNull(messageFactory);

      _constraint = constraint;
      _messageFactory = messageFactory;
    }

    public Boolean IsViolatedBy(TObject obj, TValue value)
    {
      return !_constraint.Invoke(obj, value);
    }
     
    public RuleViolation GetRuleViolation(TObject obj, TValue value)
    {
      return new RuleViolation(_messageFactory.Invoke(obj, value) ?? RuleViolations.General);
    }
  }
}